﻿using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using BotModels;
using BotTalkLibrary;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using AllBots.i18n;
using AllBots.Messaging;
using Ninject;

namespace AllBots.ViewModel
{
    public class SearchIdViewModel : ViewModelBase
    {
        private RequestMaker caller = new RequestMaker();
        private ILibraryRepository repository;

        #region INPC

        public const string IsSearchingPropertyName = "IsSearching";
        private bool isSearching = false;
        public bool IsSearching
        {
            get
            {
                return isSearching;
            }

            set
            {
                if (isSearching == value)
                {
                    return;
                }

                var oldValue = isSearching;
                isSearching = value;

                // Update bindings, no broadcast
                RaisePropertyChanged(IsSearchingPropertyName);
                searchCommand.RaiseCanExecuteChanged();
            }
        }

        public const string SearchBotPropertyName = "SearchId";
        private Bot searchBot;
        public Bot SearchBot
        {
            get
            {
                return searchBot;
            }

            set
            {
                if (searchBot == value)
                {
                    return;
                }

                var oldValue = searchBot;
                searchBot = value;

                // Update bindings, no broadcast
                RaisePropertyChanged(SearchBotPropertyName);
                Error = null;
                searchCommand.RaiseCanExecuteChanged();
            }
        }

        public const string ErrorPropertyName = "Error";
        private string error;
        public string Error
        {
            get
            {
                return error;
            }

            set
            {
                if (error == value)
                {
                    return;
                }

                var oldValue = error;
                error = value;

                // Update bindings, no broadcast
                RaisePropertyChanged(ErrorPropertyName);
            }
        }

        public const string FoundBotIdPropertyName = "FoundBotId";
        private bool foundBotId;
        public bool FoundBotId
        {
            get
            {
                return foundBotId;
            }

            set
            {
                if (foundBotId == value)
                {
                    return;
                }

                var oldValue = foundBotId;
                foundBotId = value;

                // Update bindings, no broadcast
                RaisePropertyChanged(FoundBotIdPropertyName);
            }
        }

        public const string SaveToLibraryPropertyName = "SaveToLibrary";
        private bool saveToLibrary = true;
        public bool SaveToLibrary
        {
            get
            {
                return saveToLibrary;
            }

            set
            {
                if (saveToLibrary == value)
                {
                    return;
                }

                var oldValue = saveToLibrary;
                saveToLibrary = value;

                // Update bindings, no broadcast
                RaisePropertyChanged(SaveToLibraryPropertyName);
            }
        }

        #endregion

        #region Commands

        private RelayCommand searchCommand;
        public ICommand SearchCommand
        {
            get
            {
                if (searchCommand == null)
                {
                    searchCommand = new RelayCommand(Search, ValidateSearch);
                }

                return searchCommand;
            }
        }

        #endregion

        /// <summary>
        /// Initializes a new instance of the SearchIdViewModel class.
        /// </summary>
        public SearchIdViewModel()
        {
            if (IsInDesignMode)
            {
                Error = AppResources.WrongBotId;
            }
            else
            {
                searchBot = new Bot();
                searchBot.PropertyChanged += SearchBotPropertyUpdated;
                caller.SendBotMessageCompleted += SearchCompleted;
            }

            repository = IoC.IoCContainer.Get<ILibraryRepository>();
        }

        #region Event handlers

        private void SearchCompleted(object sender, SendBotMessageEventArgs e)
        {
            if (e.Error != null)
            {
                MessageBox.Show(e.Error);
            }
            else if (e.Message.Content.Equals(RequestMaker.WRONG_BOTID_ERROR_MESSAGE))
            {
                Error = AppResources.WrongBotId;
            }
            else
            {
                Error = null;
                FoundBotId = true;
                Messenger.Default.Send(new GenericMessage<Bot>(searchBot.Clone<Bot>()));

                if (saveToLibrary)
                {
                    if (repository.AddBot(SearchBot))
                    {
                        Messenger.Default.Send(new BotAddedMessage<Bot>(searchBot.Clone<Bot>()));
                    }
                }

                // Resetting the fields
                SearchBot.Id = null;
                SearchBot.Name = null;
                SaveToLibrary = true;

                foundBotId = false;
            }

            IsSearching = false;
        }

        private void SearchBotPropertyUpdated(object sender, PropertyChangedEventArgs args)
        {
            if (args.PropertyName == Bot.IdPropertyName)
            {
                if (searchBot.Id != null && SearchBot.Id.Length == 16)
                {
                    caller.GetBotNameCompleted += (o, eventArgs) =>
                        {
                            if (eventArgs.Id == SearchBot.Id && eventArgs.Name != null)
                            {
                                SearchBot.Name = eventArgs.Name;
                                searchCommand.RaiseCanExecuteChanged();
                            }
                        };
                    caller.GetBotName(searchBot.Id);
                }
                else
                {
                    SearchBot.Name = null;
                    searchCommand.RaiseCanExecuteChanged();
                }
            }
        }

        #endregion

        private void Search()
        {
            caller.SendBotMessage(searchBot.Id, "hello");
            IsSearching = true;
        }

        private bool ValidateSearch()
        {
            return IsInDesignMode || !string.IsNullOrEmpty(searchBot.Id) && !isSearching && searchBot.Id.Length == 16 && searchBot.Name != null;
        }

        public override void Cleanup()
        {
            caller.SendBotMessageCompleted -= SearchCompleted;
            searchBot.PropertyChanged -= SearchBotPropertyUpdated;
            searchBot = null;

            base.Cleanup();
        }
    }
}